{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Perceptually uniform continuous colormaps from CET\n",
    "\n",
    "Peter Kovesi at the Center for Exploration Targeting created a very useful set of [perceptually uniform continuous colormaps](https://arxiv.org/abs/1509.03700), many of which can replace the highly non-uniform colormaps provided with Python plotting programs.  Here we will show how to use them via a Python package named [colorcet](https://github.com/pyviz/colorcet), listing all the ones available and allowing you to evaluate how perceptually uniform they are for you, your particular monitor, etc. Download and installation instructions are at the [github site](https://github.com/pyviz/colorcet).\n",
    "\n",
    "We will plot them using [Matplotlib](http://matplotlib.org) via [Holoviews](http://holoviews.org), but identical [Bokeh](http://bokeh.pydata.org) palettes are also provided, and both Bokeh palettes and Matplotlib colormaps are usable in [Datashader](https://github.com/pyviz/datashader).  Thus these colormaps can be used in any of those Python packages, as well as any other package that accepts a Python list of normalized RGB tuples or hex colors.  See \n",
    "[Peter's site](http://peterkovesi.com/projects/colourmaps/) to download versions for other non-Python packages."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import holoviews as hv\n",
    "import colorcet as cc\n",
    "from colorcet.plotting import swatches, sine_combs\n",
    "\n",
    "hv.notebook_extension(\"matplotlib\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Named colormaps\n",
    "\n",
    "The full list of colormaps included will be shown below, but a useful subset of these maps that cover the various types have been given more convenient names, and we will focus on those first."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "swatches(only_aliased=True, not_group='glasbey')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## All colormaps\n",
    "\n",
    "Each colormap has a name in the form:\n",
    "\n",
    "`{category}_{huesequence}_{lightnessrange}_c{meanchroma}[_s{colorshift}[_r]]`\n",
    "\n",
    "It is helpful to think of them by which category best suits your use case.  \n",
    "\n",
    "### Linear (sequential) colormaps, for plotting magnitudes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "swatches(group=\"linear\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Diverging colormaps, for plotting magnitudes increasing or decreasing from a central point:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "swatches(group='diverging')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Colorblind-safe colormaps (usable by people with various types of colorblindness)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "swatches(group='nopic')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Misc colormaps:\n",
    "\n",
    "* cyclic: for cyclic quantities like orientation or phase (where the highest and lowest values need the same color)\n",
    "* isoluminant: to highlight low spatial-frequency information\n",
    "* rainbow: to highlight local differences in sequential data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "misc = [name for name in cc.all_original_names() if \"cyclic\" in name or \"isoluminant\" in name or \"rainbow\" in name]\n",
    "swatches(*misc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Testing perceptual uniformity\n",
    "\n",
    "Peter Kovesi created a [test image with a sine grating modulation of intensity](http://peterkovesi.com/projects/colourmaps/colourmaptestimage.html), where modulation gain decreases from top to bottom, which helps evaluate perceptual uniformity of a colormap at a glance.  The matplotlib maintainers use different definitions of perceptually uniform (uniformity in a different color space), but the new matplotlib perceptually uniform colormaps do well at Peter's test image:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sine_combs((\"viridis\", \"viridis\"), (\"inferno\", \"inferno\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here the sine grating for a uniform colormap should be visible as a fine-toothed comb with teeth that gradually become less visible from top to bottom.  The further down the comb these teeth are visible, the higher the discriminability of magnitudes at that location in the colormap.  Thus a perceptually uniform colormap, like the two above, should have teeth that visible at the same length for all colors.  \n",
    "\n",
    "You can also use these images to evaluate the overall level of discriminability provided by a given colormap -- the longer the visible area of teeth, the better this colormap allows you to discriminate fine differences in magnitude.  Here the `inferno` map seems to have better discriminability than the `viridis` map, despite both being perceptually uniform.\n",
    "\n",
    "The default colormaps that have traditionally been used with Matlab, Matplotlib, and HoloViews are clearly not perceptually uniform --  all the green and yellow areas are nearly indistinguishable:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sine_combs((\"hot\", \"hot\"),(\"jet\", \"jet\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Thus those colormaps should be avoided if at all possible, to avoid generating misleading visualizations. Compare these two to the perceptually uniform versions provided by this package: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sine_combs(\"fire\", \"rainbow\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see the results for all the `colorcet` colormaps below, which can be summarized as:\n",
    "\n",
    "* \"linear\" colormaps all work well by this criterion\n",
    "* \"diverging\" colormaps typically have discontinuities in perceptual discriminability around the central value\n",
    "* \"cyclic\" colormaps with repeating colors tend to have discontinuities at 1/4 and 3/4 of the way through the cycle, or at other locations if shifted.\n",
    "* \"isoluminant\" colormaps typically show no visible modulation, because without luminance cues humans can only discriminate low spatial-frequency modulations (i.e., much wider teeth would be needed for evaluating such colormaps)\n",
    "* Some of the \"rainbow\" colormaps appear to have a perceptual discontinuity around the color red, the reasons for which are not yet clear."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sine_combs(not_group='glasbey', cols=2)"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
